GM.Round = 0
GM.RoundStarted = false
GM.RoundTime = 0

GM.SpawnTime = 60*4 //Four minutes to spawn in the game
GM.Spawned = {}

function GM:NewRound()
	local self = gmod.GetGamemode()
	
	if self.Round >= 0 then //More then 1 round (cleanup)
		self.RoundStarted = false
		self.RoundTime = CurTime() + 60
		for k,v in pairs(player.GetAll()) do
			self.Spawned = {}
			v:ConCommand("r_cleardecals")
			if not (self.pldat[v:UniqueID()] and self.pldat[v:UniqueID()].pigeon) then
				v:KillSilent()
				v:Spawn()
				v:WSPigeon()
			end
			
			self:updateTimer(v)
		end
		
		//Remove dropped items
		for k,v in pairs(ents.FindByClass("ws_item")) do
			v:Remove()
		end
		
		//Remove birds
		for k,v in pairs(self.bird) do
			if IsValid(k) then
				k:Remove()
			end
		end
		self.birds = {}
		
		//Remove bird bodies
		//for k,v in pairs(ents.FindByClass()) do
		//end
		
		//Remove buildings
		for k,v in pairs(self.buildingdata) do
			for i,o in pairs(v.ents) do
				o:Remove()
			end
		end
		
		//Remove arrows
		for k,v in pairs(ents.FindByClass("ws_arrow")) do
			v:Remove()
		end
		
		//Clear building data
		for k,v in pairs(player.GetAll()) do
			v:SendLua('gmod.GetGamemode().buildingdata = {}') //Garry himself says this okay. All hail Garry. As if we're killing enough bandwidth here.
		end
		//umsg.Start()
		self.buildingdata = {}
		
		//Spawn items
		self.doodadSpawnItems()
	end
	self.Round = self.Round + 1
	if self.Round == 4 then //After third round
		//Placeholder
	else
	end
end

function GM:StartRound()
	if not self.RoundStarted then
		self.Spawned = {}
		self.RoundStarted = true
		self.pl_s_game = {}
		
		for k,pl in pairs(player.GetAll()) do
			//pl:WSHuman()
			pl:KillSilent()
			pl:Spawn()
			self:updateTimer(pl)
		end
		//PrintTable(self.pl_s_game)
		
		for k,v in pairs(player.GetAll()) do
			if v:IsConnected() and v:Alive() then
				if v:WSIsPigeon() then //Spectator
				else //In game
				end
			end
		end
		hook.Call("StartRound",self)
	end
end

if SERVER then
	concommand.Add("ws_startround",function(pl,cmd,args)
		if pl:IsAdmin() then
			gmod.GetGamemode():StartRound()
		end
	end)
	
	concommand.Add("ws_newround",function(pl,cmd,args)
		if pl:IsAdmin() then
			gmod.GetGamemode():NewRound()
		end
	end)
end

function GM:IsRoundStarted()
	return self.RoundStarted
end

function GM:RoundPlayerSpawn(pl)
	self:updateTimer(pl)
	if not self:IsRoundStarted() then
		pl:WSPigeon()
	else
		local fail = false
		
		local uid = pl:UniqueID()
		if self.Spawned[uid] then
			fail = true
		else
			self.Spawned[uid] = true
		end
		
		if CurTime() - self.RoundTime > self.SpawnTime then
			fail = true
		end
		
		if not fail then
			table.insert(self.pl_s_game,pl)
			//PrintTable(self.pl_s_game)
			pl:WSHuman(true)
		else
			pl:WSPigeon()
		end
	end
end

function GM:LoadNextLevel()
	
end

function GM:updateTimer(pl)
	umsg.Start("wsTimer",pl)
		if self:IsRoundStarted() then
			umsg.Bool("false")
		else
			umsg.Bool("true")
			umsg.Float(self.RoundTime)
		end
	umsg.End()
end

hook.Add("Think","wsroundthink",function()
	local self = gmod.GetGamemode()
	if not self:IsRoundStarted() and CurTime() > self.RoundTime then
		self:StartRound()
	elseif self:IsRoundStarted() then
		//End-game logic
		
		if SinglePlayer() or MaxPlayers() <= 1 then
			if player.GetByID(1):WSIsPigeon() or !(player.GetByID(1):Alive()) then
				self:NewRound()
			end
			return
		end
		
		self.pl_spec = {}
		self.pl_game = {}
		for k,v in pairs(player.GetAll()) do
			if v:IsConnected() and v:Alive() then
				if v:WSIsPigeon() or !(v:Alive()) then //Spectator
					table.insert(self.pl_spec,v)
				else //In game
					table.insert(self.pl_game,v)
				end
			end
		end
		
		local endgame = false
		local winner
		
		if #self.pl_spec > 0 then //If there are people waiting to play
			if #self.pl_game == 1 then
				if #self.pl_s_game > 1 then
					winner = self.pl_game[1]
				end
				endgame = true
			elseif #self.pl_game == 0 then
				endgame = true
			end
		end
		
		if endgame then
			local rf = RecipientFilter()
			rf:AddAllPlayers()
			if winner then
				umsg.Start("wsWinner",rf)
					umsg.String(tostring(winner:Name()))
					umsg.Float(CurTime())
				umsg.End()
				
				winner:AddFrags(1)
			else
				umsg.Start("wsWinner",rf)
					umsg.String("No one")
					umsg.Float(CurTime())
				umsg.End()
			end
			self:NewRound()
		end
	end
end)

FindMetaTable("Player").WSPigeon = function(self)
	local GM = gmod.GetGamemode()
	local uid = self:UniqueID()
	if !self:Alive() then
		self:Spawn()
	elseif not self:WSIsPigeon() then
		local class = ""
		local dat = GM.pldat[uid]
		if dat then
			class = GM.pldat[uid].invsel
		end
		if dat then
			dat = GM.items[class]
		end
		if dat then
			local a = dat
			
			if a then
				a = a.onInvUnSelect
				if a then
					local b,err = pcall(a,dat,self) //ITEM:onInvUnSelect(pl)
					if not b then
						Error("\n",err)
					end
				end
			end
		end
		//End
		
	end
	local pigeon = ents.Create("ws_pigeon")
	pigeon:SetPos(self:GetPos())
	pigeon:GetTable().Owner = self
	pigeon:Spawn()
	
	if GM.pldat[uid].pigeon and IsValid(GM.pldat[uid].pigeon) then
		GM.pldat[uid].pigeon:die(true)
	end
	
	GM.pldat[uid].pigeon = pigeon
	self:SpectateEntity(pigeon)
	self:Spectate(OBS_MODE_CHASE)
	
	umsg.Start("wsPigeonStatus",self)
		umsg.Bool(true)
	umsg.End()
end

FindMetaTable("Player").WSIsPigeon = function(self)
	local GM = gmod.GetGamemode()
	local uid = self:UniqueID() or -1
	if GM.pldat[uid].pigeon and IsValid(GM.pldat[uid].pigeon) then
		return true
	end
	return false
end

FindMetaTable("Player").WSHuman = function(self)
	local GM = gmod.GetGamemode()
	if !self:Alive() then
		self:Spawn()
	end
	
	local uid = self:UniqueID()
	if GM.pldat[uid].pigeon then
		GM.pldat[uid].pigeon:die(true)
	end
	self:UnSpectate()
	
	hook.Call("PlayerLoadout",GM,self)
	//self:Give("ws_empty")
	GM.pldat[self:UniqueID()] = {
		inventory = {},
		invsel = nil,
	}
	
	GM:updateInventory(self)
	GM:resetNet(self)
	GM:sendNet(self)
	GM:resetNeeds(self)
	
	umsg.Start("wsPigeonStatus",self)
		umsg.Bool(false)
	umsg.End()
end

function GM:PlayerDisconnected( pl )
	local self = gmod.GetGamemode()
	self:DoPlayerDeath( pl, "", pl )
end

//Pigeon hooks

hook.Add("PlayerDeath","wspigeon",function(pl,inf,killer)
	local GM = gmod.GetGamemode()
	local uid = pl:UniqueID()
	
	if GM.pldat[uid].pigeon and IsValid(GM.pldat[uid].pigeon) then
		GM.pldat[uid].pigeon:die(killer == pl)
	end
end)